import json
import logging
import time
import urllib.parse

import requests
import requests.auth

from coin.exchange.base.kr_rest.rest_client_base import RestUpdate
from coin.exchange.util.rate_limit import RateLimiter

LMAXDIGITAL_API_URL = "api.lmaxdigital.io"

class LmaxdigitalAuth(requests.auth.AuthBase):
  def __init__(self, key_file):
    with open(key_file) as content:
        self._key = json.load(content)
    self._api_key = "ec18a731509b47e89d3ccf89b777f902"
    self._data = {
        'venue': 'DIGITAL',
        'loginCount': 0,
        'user': self._key['rest_username'],
        'pass': self._key['rest_password'],
        'api_key': self._api_key
    }

  def __call__(self, req: requests.PreparedRequest):
    req.headers.update({
      "Content-Type": "application/json; charset=utf-8"
    })
    return req


class LmaxdigitalSyncQueryer(object):
  def __init__(self, key_file, *, api_host=None, timeout=10):
    self._timeout = timeout
    self._auth = LmaxdigitalAuth(key_file)
    self._api_host = "https://" + (api_host or LMAXDIGITAL_API_URL)
    self.rate_limit = RateLimiter(20, 1)
    self._logger = logging.getLogger(__name__)

  def auth_request(self, method, path):
    assert method == 'POST', method
    url = urllib.parse.urljoin(self._api_host, path)
    response = None
    try:
      response = requests.request(method,
                                  url,
                                  data=json.dumps(self._auth._data),
                                  auth=self._auth,
                                  timeout=self._timeout)
      content = response.json()
      return content
    except requests.exceptions.RequestException as e:
      self._logger.exception('RequestException: %s', e)
      raise
    except json.JSONDecodeError as e:
      self._logger.exception('JsonDecodeException: %s\n %s', response.content, e)
      raise
    except Exception as e:
      self._logger.exception('Unknown exception, %s', e)
      raise

  def _query_nocheck(self, method, path):
    req_timestamp = time.time()
    content = self.auth_request(method, path)
    res_timestamp = time.time()
    status = requests.codes.ok
    update = RestUpdate(req_timestamp, res_timestamp, content, status)
    return update

  def query(self, method, path, disable_rate_limit=False):
    if not disable_rate_limit:
      while not self.rate_limit.check():
        time.sleep(0.1)
    else:
      self.rate_limit.check()
    return self._query_nocheck(method, path)


class LmaxdigitalNativePrivateClient(object):
  def __init__(self, *, key_file, api_host=None, timeout=10):
    self._auth_queryer = LmaxdigitalSyncQueryer(
      key_file, api_host=api_host, timeout=timeout)

  def _query(self, method, path):
    return self._auth_queryer.query(method, path)

  def query_account_balance(self):
    method = 'POST'
    path = '/accountview/accountstatejson'
    update = self._query(method, path)
    return update


if __name__ == "__main__":
  client00 = LmaxdigitalNativePrivateClient(
    key_file='../../coin_key/view/xunke00/lmax_digital/view_key.json')
  resp0 = client00.query_account_balance()
  print(resp0)

  client01 = LmaxdigitalNativePrivateClient(
    key_file='../../coin_key/view/xunke01/lmax_digital/view_key.json')
  resp1 = client01.query_account_balance()
  print(resp1)

